// 条件类型的内置类型

interface Bird {
  name: "鸟";
}
interface Fish {
  name: "鱼";
}
interface Sky {
  color: "蓝色";
}
interface Water {
  color: "白色";
}
// js中的三元表达式   extends在这里你可以认为是条件

// 定义泛型的时候 增加的extends 是对泛型的约束 ， 后面的extends 是条件
type ISelect<T extends Bird | Fish> = T extends Bird ? Sky : Water; // in 在ts中指代的是循环

// ts 中有分发的概念 ，只有联合类型能被分发
type MyColor = ISelect<Bird | Fish>; // 联合类型能分发  交叉类型不能分发

// Exclude Extract  非空 都是基于条件类型的

// type Exclude<T,K> = T extends K ? never:T   // 排除 找到不想要的扔出去（知道哪些不想要）
type MyInclude = Exclude<number | string | boolean, boolean>;

// type Extract<T, K> = T extends K ? T : never; // 抽离 需要哪些留下哪些
type MyExtract = Extract<number | string | boolean, boolean | string>;

// 用户传入数据 有空的类型

let ele = document.getElementById("APP");
// type NonNullable<T> = T extends null | undefined ? never : T;
type EType = NonNullable<typeof ele>;

// --------------------------------END 条件------------------------------
interface Company {
  name: string;
  age: number;
}
interface IPerson {
  name: string;
  age: number;
  company: Company;
}
// 1)
// type Partial<T> = { [P in keyof T]?: T[P] };
// type PartialPerson = Partial<IPerson>;
// 2)
// type Required<T> = { [P in keyof T]-?: T[P] };
// type RequiredPerson = Required<PartialPerson>;
// 3)
// type Readonly<T> = { readonly [P in keyof T]: T[P] };
// let obj = {name:'zf',age:{n:100}} as const; // ts可以让对象中的属性标记成仅读的
// type ReadonlydPerson = Readonly<RequiredPerson>;

// 4) 循环 + 条件 + 递归

type DeepPartial<T> = {
  [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};
type PartialPerson = DeepPartial<IPerson>;
let person: PartialPerson = {
  company: {},
};

// Pick 挑选 Omit 在众多属性中忽略某几个

// 1)
// type Pick<T extends object, K extends keyof T> = { [P in K]: T[P] };
// type PickPerson = Pick<IPerson, "name" | "age">; // Extract 众多类型中挑选某几个  Pick是在对象里挑

// 2)
type Omit<T extends object, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
type OmitPerson = Omit<IPerson, "name" | 'age'>; // 1） 拿到所有的key 排除掉当前的key  通过需要的在挑选出来



// Record 描述对象的key value格式  对象-> 映射
// type Record<K extends keyof any, V> = { [P in K]: V; } // 就是设计了一个映射的类型  就是任意属性 

function map<K extends keyof any,V,U>(obj:Record<K,V>,fn:(value:V,key:K)=>U ):Record<K,U>{
    let result = {} as Record<K,U>;
    for(let key in obj){
        result[key] = fn(obj[key],key)
    }
    return result
}
let returnValue = map({a:'a',b:'b'},(value,key)=>{  //{a:'a',b:'b'} =>  {a:'aa',b:ba}
    return value+'a'
});

// 内置类型有哪些？  Exclude Extract NonNullable 三元   Partial readOnly required Pick 循环 Omit
// Record


// 我希望这么多属性中 只让 name， 和 age是可选的 ？   在对象中跳出来name和age + ？ 其他的在忽略掉 name + age &


// ----------------------------------交集never问题----------------------------------
// let a = {a:1,b:'sss'}
// let b = {b:2}
// let c:typeof a& typeof b = {...a,...b}

// interface P1 {
//     a:string
// }
// interface P2 {
//     a:number
// }
// let x!:never
// let p3:P1 & P2 = {
//   a:x
// }
export {};
